#include "application.h"
#include "drv_l2_sensor.h"
INT8U ScalerFactorX = 0,ScalerFactorY = 0;
typedef struct
{
	INT16U zoom_width;
	INT16U zoom_height;
	INT16U zoom_w_start;
	INT16U zoom_h_start;
} ZOOM_PARM;

typedef struct
{
	INT16U	ap_mode;
	const ZOOM_PARM* zoom_parm;
	INT8U	num;
} AP_ZOOM_PARM;

typedef struct
{
	INT16U	tft_w;
	INT16U	tft_h;
	const AP_ZOOM_PARM* ap_zoom_parm;
	INT8U	num;
} TFT_ZOOM_PARM_T;

#if (C_REAR_ONLY == CUSTOM_OFF)
static const ZOOM_PARM zoom_parm_220_176_capture[] =
{
#if ((FRONT_SENSOR_WIDTH == 1280) && (FRONT_SENSOR_HEIGHT == 720))
        // 12M (4032 x 3024)
        {234, 176, 54, 0},
        // 10M (3648 x 2736)
        {234, 176, 54, 0},
        // 8M (3264 x 2448)
        {234, 176, 54, 0},
        // 5M (2592 x 1944)
        {234, 176, 54, 0},
        // 3M (2048 x 1536)
        {234, 176, 54, 0},
        // 2MHD (1920 x 1080)
        {312, 176, 214, 0},
        // 1.3M (1280 x 960)
        {234, 176, 54, 0},
        // VGA (640 x 480)
        {234, 176, 54, 0},
#elif ((FRONT_SENSOR_WIDTH == 1920) && (FRONT_SENSOR_HEIGHT >= 1080) && (FRONT_SENSOR_HEIGHT <= 1088))

#endif
};

static const ZOOM_PARM zoom_parm_220_176_record[] =
{
#if ((FRONT_SENSOR_WIDTH == 1280) && (FRONT_SENSOR_HEIGHT == 720))
        // 1080FHD (1920 x 1080)
        {312, 176, 214, 0},
        // 1080P (1440 x 1080)
        {234, 176, 54, 0},
        // 720P (1280 x 720)
        {312, 176, 214, 0},
        // WVGA (800 x 480)
        {312, 176, 214, 0},
        // VGA (640 x 480)
        {234, 176, 54, 0},
        // QVGA (320 x 240)
        {234, 176, 54, 0},
#elif ((FRONT_SENSOR_WIDTH == 1920) && (FRONT_SENSOR_HEIGHT >= 1080) && (FRONT_SENSOR_HEIGHT <= 1088))
#endif
};

static const AP_ZOOM_PARM ap_zoom_parm_220_176[] =
{
    {
        STATE_PHOTO_CAPTURE,
        zoom_parm_220_176_capture_r, 8
    }
    ,
    {
        STATE_VIDEO_RECORD,
        zoom_parm_220_176_record_r, 6
    },
};

static const TFT_ZOOM_PARM_T tft_zoom_parm[] =
{
	{
	    208, 176,
		ap_zoom_parm_220_176, 2
	}
};

static INT32S video_encode_zoom_config(VIDEO_ARGUMENT* arg, INT8U reso)
{
	INT32U i, j;

	for(i = 0 ; i < sizeof(tft_zoom_parm) / sizeof(TFT_ZOOM_PARM_T) ; ++i)
	{
		if( (tft_zoom_parm[i].tft_w && tft_zoom_parm[i].tft_h)
			&& (arg->DisplayWidth == tft_zoom_parm[i].tft_w)
			&& (arg->DisplayHeight == tft_zoom_parm[i].tft_h)
		)
		{
			for(j = 0 ; j < tft_zoom_parm[i].num ; ++j)
			{
				if(arg->bEnterApMode == tft_zoom_parm[i].ap_zoom_parm[j].ap_mode)
				{
					if(reso < tft_zoom_parm[i].ap_zoom_parm[j].num)
					{
						arg->ZoomWidth	= tft_zoom_parm[i].ap_zoom_parm[j].zoom_parm[reso].zoom_width;
						arg->ZoomHeight	= tft_zoom_parm[i].ap_zoom_parm[j].zoom_parm[reso].zoom_height;
						arg->ZoomWStart	= tft_zoom_parm[i].ap_zoom_parm[j].zoom_parm[reso].zoom_w_start;
						arg->ZoomHStart	= tft_zoom_parm[i].ap_zoom_parm[j].zoom_parm[reso].zoom_h_start;

						#if 0
						DBG_PRINT("arg(width, height, w_start, h_start)=(%d, %d, %d, %d)\r\n"
							, arg->ZoomWidth
							, arg->ZoomHeight
							, arg->ZoomWStart
							, arg->ZoomHStart
						);
						#endif

						return STATUS_OK;
					}
					break;
				}
			}
			break;
		}
	}

	return STATUS_FAIL;
}
#endif
//===================================================================
static const ZOOM_PARM zoom_parm_220_176_capture_r[] = 
{ 
	{312, 176, 214, 0}, //720P//189
	{234, 176, 36, 0}, //VGA
};

static const ZOOM_PARM zoom_parm_220_176_record_r[] = 
{ 
	{312, 176, 214, 0}, //720P
	{234, 176, 36, 0}, //VGA
};

static const AP_ZOOM_PARM ap_zoom_parm_220_176_r[] = 
{ 
    { 
        STATE_PHOTO_CAPTURE, 
        zoom_parm_220_176_capture_r, 2
    } 
    , 
    { 
        STATE_VIDEO_RECORD, 
        zoom_parm_220_176_record_r, 2
    }, 
}; 

static const TFT_ZOOM_PARM_T tft_zoom_parm_r[] =
{
	{
		208, 176,
		ap_zoom_parm_220_176_r, 2
	}
};

static INT32S video_encode_zoom_config_r(VIDEO_ARGUMENT* arg, INT8U reso)
{
	INT32U i, j;

	for(i = 0 ; i < sizeof(tft_zoom_parm_r) / sizeof(TFT_ZOOM_PARM_T) ; ++i)
	{
		if( (tft_zoom_parm_r[i].tft_w && tft_zoom_parm_r[i].tft_h)
			&& (arg->DisplayWidth == tft_zoom_parm_r[i].tft_w)
			&& (arg->DisplayHeight == tft_zoom_parm_r[i].tft_h)
		)
		{
			for(j = 0 ; j < tft_zoom_parm_r[i].num ; ++j)
			{
				if(arg->bEnterApMode == tft_zoom_parm_r[i].ap_zoom_parm[j].ap_mode)
				{
					arg->ZoomWidth_r	= tft_zoom_parm_r[i].ap_zoom_parm[j].zoom_parm[reso].zoom_width;
					arg->ZoomHeight_r	= tft_zoom_parm_r[i].ap_zoom_parm[j].zoom_parm[reso].zoom_height;
					arg->ZoomWStart_r	= tft_zoom_parm_r[i].ap_zoom_parm[j].zoom_parm[reso].zoom_w_start;
					arg->ZoomHStart_r	= tft_zoom_parm_r[i].ap_zoom_parm[j].zoom_parm[reso].zoom_h_start;

					#if 0
					DBG_PRINT("arg(width_r, height_r, w_start_r, h_start_r)=(%d, %d, %d, %d)\r\n"
						, arg->ZoomWidth_r
						, arg->ZoomHeight_r
						, arg->ZoomWStart_r
						, arg->ZoomHStart_r
					);
					#endif

					return STATUS_OK;
				}
			}
			break;
		}
	}

	return STATUS_FAIL;
}

extern INT8U gApp_Select_Res;
extern INT8U gUSB20_11_Connect;
static INT32S video_encode_resolution_get(VIDEO_ARGUMENT* arg, INT16U APMode)
{
    INT8U video_resolution, video_resolution_r;

	arg->bScaler = 1;

#if C_SENSOR_SAVE_RAW_DATA
	APMode = STATE_VIDEO_RECORD;
#endif

	if(APMode == STATE_PHOTO_CAPTURE)
	{
		DBG_PRINT("<<STATE_PHOTO_CAPTURE\r\n");

#if _SENSOR_CSI_FRONT
		drv_l2_user_sensor_csi_scale_up_set(1);
		arg->TargetWidth	= AVI_WIDTH_D1;
		arg->TargetHeight	= AVI_HEIGHT_D1;
		arg->SensorWidth	= drv_l2_user_sensor_width_get();
		arg->SensorHeight	= drv_l2_user_sensor_height_get();
		arg->ClipWidth		= arg->SensorWidth;
		arg->ClipHeight		= arg->SensorHeight;
#else // #if _SENSOR_CSI_FRONT

		video_resolution = ap_state_config_pic_size_get();

		switch(video_resolution)
		{
		case 0:		// 4032*3024
			arg->SensorWidth	= 960;
			arg->SensorHeight	= AVI_HEIGHT_720P;
			arg->TargetWidth	= 4032;
			arg->TargetHeight	= 3024;
		break;
		case 1:		// 3648*2736
			arg->SensorWidth	= 960;
			arg->SensorHeight	= AVI_HEIGHT_720P;
			arg->TargetWidth	= 3648;
			arg->TargetHeight	= 2736;
		break;
		case 2:		// 3264*2448
			arg->SensorWidth	= 960;
			arg->SensorHeight	= AVI_HEIGHT_720P;
			arg->TargetWidth	= 3264;
			arg->TargetHeight	= 2448;
		break;
		case 3:		// 2592*1944
			arg->SensorWidth	= 960;
			arg->SensorHeight	= AVI_HEIGHT_720P;
			arg->TargetWidth	= 2592;
			arg->TargetHeight	= 1944;
		break;
		case 4:		// 2048*1536
			arg->SensorWidth	= 960;
			arg->SensorHeight	= AVI_HEIGHT_720P;
			arg->TargetWidth	= 2048;
			arg->TargetHeight	= 1536;
		break;
		case 6:		// 1280*960
			arg->SensorWidth	= 960;
			arg->SensorHeight	= AVI_HEIGHT_720P;
			arg->TargetWidth	= 1280;
			arg->TargetHeight	= 960;
		break;
		case 7:		// 640*480
			arg->SensorWidth	= 960;
			arg->SensorHeight	= AVI_HEIGHT_720P;
			arg->TargetWidth	= 640;
			arg->TargetHeight	= 480;
		break;
		case 5:		// 1920*1080
			arg->TargetWidth	= 1920;
			arg->TargetHeight	= 1080;
			arg->SensorWidth	= AVI_WIDTH_720P;
			arg->SensorHeight	= AVI_HEIGHT_720P;
		break;
		}

		arg->ClipWidth	= arg->SensorWidth;
		arg->ClipHeight	= arg->SensorHeight;

#endif // #if _SENSOR_CSI_FRONT
	}
	else
	if(APMode == STATE_VIDEO_RECORD)
	{
		DBG_PRINT("<<STATE_VIDEO_RECORD\r\n");

#if _SENSOR_CSI_FRONT
		drv_l2_user_sensor_csi_scale_up_set(1);
		arg->TargetWidth	= AVI_WIDTH_D1;
		arg->TargetHeight	= AVI_HEIGHT_D1;
		arg->SensorWidth	= drv_l2_user_sensor_width_get();
		arg->SensorHeight	= drv_l2_user_sensor_height_get();
		arg->ClipWidth	= arg->SensorWidth;
		arg->ClipHeight = arg->SensorHeight;
#else // #if _SENSOR_CSI_FRONT

		video_resolution = ap_state_config_video_resolution_get();

		#if C_SENSOR_SAVE_RAW_DATA
		video_resolution = 2;
		#endif

		switch(video_resolution)
		{
		case 0:		//1080FHD 1920X1080
			arg->TargetWidth	= AVI_WIDTH_1080FHD;
			arg->TargetHeight	= AVI_HEIGHT_1080FHD;
			arg->SensorWidth	= AVI_WIDTH_720P;
			arg->SensorHeight	= AVI_HEIGHT_720P;
		break;
		case 1:		//1080P 1440X1080
			arg->TargetWidth	= AVI_WIDTH_1080P;
			arg->TargetHeight	= AVI_HEIGHT_1080P;
			arg->SensorWidth	= 960;
			arg->SensorHeight	= AVI_HEIGHT_720P;
		break;
		case 2:		//720P 1280X720
		default:	//default
			arg->TargetWidth	= AVI_WIDTH_720P;
			arg->TargetHeight	= AVI_HEIGHT_720P;
			arg->SensorWidth	= AVI_WIDTH_720P;
			arg->SensorHeight	= AVI_HEIGHT_720P;
		break;
		case 3:		//WVGA 800X480
			arg->TargetWidth	= AVI_WIDTH_WVGA;
			arg->TargetHeight	= AVI_HEIGHT_WVGA;
			arg->SensorWidth	= AVI_WIDTH_WVGA;
			arg->SensorHeight	= AVI_HEIGHT_WVGA;
		break;
		case 4:		//VGA 640X480
			arg->TargetWidth	= AVI_WIDTH_VGA;
			arg->TargetHeight	= AVI_HEIGHT_VGA;
			arg->SensorWidth	= AVI_WIDTH_VGA;
			arg->SensorHeight	= AVI_HEIGHT_VGA;
		break;
		case 5:		//QVGA 320X240
			arg->TargetWidth	= AVI_WIDTH_QVGA;
			arg->TargetHeight	= AVI_HEIGHT_QVGA;
			arg->SensorWidth	= AVI_WIDTH_QVGA;
			arg->SensorHeight	= AVI_HEIGHT_QVGA;
		break;
		}

		arg->ClipWidth	= arg->SensorWidth;
		arg->ClipHeight	= arg->SensorHeight;

#endif // #if _SENSOR_CSI_FRONT

	}
	else
	if(APMode == STATE_CONNECT_TO_PC)
	{
		#if _SENSOR_CSI_FRONT
		// only VGA size in UVC mode
		drv_l2_user_sensor_csi_scale_up_set(0);
		arg->TargetWidth	= AVI_WIDTH_VGA;
		arg->TargetHeight	= AVI_HEIGHT_VGA;
		arg->SensorWidth	= drv_l2_user_sensor_width_get();
		arg->SensorHeight	= drv_l2_user_sensor_height_get();
		arg->ClipWidth		= arg->SensorWidth;
		arg->ClipHeight		= arg->SensorHeight;
		#else // #if _SENSOR_CSI_FRONT

		#if 0
		arg->TargetWidth	= AVI_WIDTH_VGA;
		arg->TargetHeight	= AVI_HEIGHT_VGA;
		arg->SensorWidth	= AVI_WIDTH_VGA;
		arg->SensorHeight	= AVI_HEIGHT_VGA;
		#else
		arg->TargetWidth	= AVI_WIDTH_720P;
		arg->TargetHeight	= AVI_HEIGHT_720P;
		arg->SensorWidth	= AVI_WIDTH_720P;
		arg->SensorHeight	= AVI_HEIGHT_720P;
		#endif
		arg->ClipWidth		= arg->SensorWidth;
		arg->ClipHeight		= arg->SensorHeight;
		#endif // #if _SENSOR_CSI_FRONT
	}
	else
	{
		do
		{
			DBG_PRINT("[ERROR]wrong APMode=%d\r\n, @%s:%d", APMode, __func__, __LINE__);
		}
		while(0);
		video_encode_resolution_get(arg, APMode);
	}

  	arg->DisplayOffset	= drv_l2_display_frame_y_get();//20;
	arg->DisplayWidth	= drv_l2_display_tft_width_get();
	arg->DisplayHeight	= drv_l2_display_tft_height_get() - arg->DisplayOffset;//-32;
	


	arg->PipX			= drv_l2_display_pip_x_get();
	arg->PipY			= drv_l2_display_pip_y_get();
	arg->PipWidth		= drv_l2_display_pip_width_get();
	arg->PipHeight		= drv_l2_display_pip_height_get();

	arg->bEnterApMode	= APMode;
	arg->VidFrameRate	= AVI_FRAME_RATE;
	arg->AudSampleRate	= AUD_REC_SAMPLING_RATE;
	arg->OutputFormat	= IMAGE_OUTPUT_FORMAT_RGB565;

	#if ENABLE_REAR_FUNC

	#if ENABLE_REAR_SENSOR_FROM_HOST_UVC

	if(gApp_Select_Res==1)//720p
	{
		//arg->TargetWidth_r	= FRAME_WIDTH_VGA;
		//arg->TargetHeight_r	= FRAME_HEIGHT_VGA;
		//arg->TargetWidth_r	= FRAME_WIDTH_720P;
		//arg->TargetHeight_r	= FRAME_HEIGHT_720P;
		arg->TargetWidth_r	= FRAME_WIDTH_1080P;
		arg->TargetHeight_r	= FRAME_HEIGHT_1080P;	

		
		black_jpg = (INT32U)black_jpg_720p;
		black_jpg_len = black_jpg_len_720p;
	}
	else
	{
#if 1
		DBG_PRINT("sensor is here...\r\n");
		arg->SensorWidth_r	= FRAME_WIDTH_VGA;
		arg->SensorHeight_r	= FRAME_HEIGHT_VGA;
		if(APMode == STATE_PHOTO_CAPTURE)
		{
			DBG_PRINT("<<STATE_PHOTO_CAPTURE111\r\n");
			video_resolution = ap_state_config_pic_size_get();
			switch(video_resolution)
			{
				case 0:	// 1M	
					arg->TargetWidth_r	= 960;//1280;
					arg->TargetHeight_r	= 720;
				break;
				case 1:	// 2M
					arg->TargetWidth_r	= 1440;//1920;
					arg->TargetHeight_r	= 1080;
				break;
				case 2:	// 3M
					arg->TargetWidth_r	= 2560;
					arg->TargetHeight_r	= 1920;//1440;
				break;
			}
#if C_SPI_FLASH_DISK
			if(ap_state_handling_storage_id_get() == NO_STORAGE)
			{
				arg->TargetWidth_r	= 640;
				arg->TargetHeight_r	= 480;
			}
#endif
		}
		else if(APMode == STATE_VIDEO_RECORD)
		{
			DBG_PRINT("<<STATE_VIDEO_RECORD1111\r\n");
			video_resolution = ap_state_config_video_resolution_get();
			switch(video_resolution)
			{
			
				case 0:	// VGA	 640X480
					arg->TargetWidth_r	= AVI_WIDTH_VGA;
					arg->TargetHeight_r	= AVI_HEIGHT_VGA;
				break;
				case 1:	// HD	1280X720
					arg->TargetWidth_r	= AVI_WIDTH_1080P;//AVI_WIDTH_720P;
					arg->TargetHeight_r	= AVI_HEIGHT_1080P;//AVI_HEIGHT_720P;

/*
				arg->TargetWidth_r	= AVI_WIDTH_1080FHD;
				arg->TargetHeight_r	= AVI_HEIGHT_1080FHD;
				
				arg->TargetWidth_r	= AVI_WIDTH_1080P;
				arg->TargetHeight_r	= AVI_HEIGHT_1080P;
*/
			}
		}
#else
		arg->SensorWidth_r	= FRAME_WIDTH_VGA;
		arg->SensorHeight_r	= FRAME_HEIGHT_VGA;
		//arg->TargetWidth_r	= FRAME_WIDTH_VGA;
		//arg->TargetHeight_r	= FRAME_HEIGHT_VGA;
		//arg->TargetWidth_r	= FRAME_WIDTH_720P;
		//arg->TargetHeight_r	= FRAME_HEIGHT_720P;
		arg->TargetWidth_r	= FRAME_WIDTH_1080P;
		arg->TargetHeight_r	= FRAME_HEIGHT_1080P;
		
		//arg->TargetWidth_r	= FRAME_WIDTH_VGA;
		//arg->TargetHeight_r	= FRAME_HEIGHT_VGA;
#endif
		black_jpg = (INT32U)black_jpg_vga;
		black_jpg_len = black_jpg_len_vga;
		
	}
	

	DBG_PRINT("arg->TargetWidth_r=%d arg->TargetHeight_r=%d\r\n",arg->TargetWidth_r, arg->TargetHeight_r);
	#else // #if ENABLE_REAR_SENSOR_FROM_HOST_UVC
	arg->SensorWidth_r	= REAR_SENSOR_WIDTH;
	arg->SensorHeight_r	= REAR_SENSOR_HEIGHT;
	arg->TargetWidth_r	= AVI_WIDTH_D1;
	arg->TargetHeight_r	= AVI_HEIGHT_D1;
	#endif // #if ENABLE_REAR_SENSOR_FROM_HOST_UVC

	arg->VidFrameRate_r	= AVI_FRAME_RATE_REAR;
	#endif // #if ENABLE_REAR_FUNC

#if (C_REAR_ONLY == CUSTOM_OFF)
	if(STATUS_OK != video_encode_zoom_config(arg, video_resolution))
	{
		arg->ZoomWidth	= arg->DisplayWidth;
		arg->ZoomHeight	= arg->DisplayHeight;
		arg->ZoomWStart	= 0;
		arg->ZoomHStart	= 0;
	}
#endif	
	
	if(gUSB20_11_Connect)
	{
		video_resolution_r = 0;	//720P
	}
	else
	{
		video_resolution_r = 1;		//VGA
	}
		
	if(STATUS_OK != video_encode_zoom_config_r(arg, video_resolution_r))
	{
		
		arg->ZoomWidth_r	= arg->DisplayWidth;
		arg->ZoomHeight_r	= arg->DisplayHeight; 
		arg->ZoomWStart_r	= 0;
		arg->ZoomHStart_r	= 0;
	}
	
	return STATUS_OK;
}

void video_encode_entrance(void)
{
	INT32S	nRet;

	DBG_PRINT("=>video_encode_entrance!!!\r\n");

	avi_encode_init();

	nRet = avi_encode_state_task_create(PRIORITY_AVI_ENC);
	if(nRet < 0)
	{
		DBG_PRINT("avi_encode_state_task_create fail !!!");
	}

	nRet = avi_adc_record_task_create(PRIORITY_AUD_ENC);
	if(nRet < 0)
	{
		DBG_PRINT("avi_adc_record_task_create fail !!!");
	}
	else
	{
		// register UART RX for GPS function
		//avi_adc_gps_register();
		//ap_peripheral_gsensor_data_register();
	}

	nRet = avi_encode_packer_memory_alloc();
	if(nRet < 0)
	{
		DBG_PRINT("avi_encode_packer_memory_alloc fail !!!");
	}

	pAviEncPacker0->return_queue = videoEncodeApQ;
	pAviEncPacker0->return_msg = AVIPACKER_MSG_VIDEO_WRITE_DONE;
	pAviEncPacker0->print_flag = 1;
	pAviEncPacker0->front_or_rear = 0;	//front
	pAviEncPacker1->return_queue = videoEncodeApQ;
	pAviEncPacker1->return_msg = AVIPACKER_MSG_VIDEO_WRITE_DONE1;

#if (C_REAR_ONLY == CUSTOM_OFF)
	pAviEncPacker1->print_flag = 0;
#else
	pAviEncPacker1->print_flag = 1;
#endif

	pAviEncPacker1->front_or_rear = 1;	//rear
	avi_enc_packer_init(pAviEncPacker0);
	avi_enc_packer_init(pAviEncPacker1);
}

CODEC_START_STATUS video_encode_sensor_on(INT16U APMode)
{
	INT32S			nRet;
	VIDEO_ARGUMENT	arg;

	DBG_PRINT("=>video_encode_sensor_on!!!\r\n");

	video_encode_resolution_get(&arg, APMode);

	pAviEncAudPara->audio_format		= AVI_ENCODE_AUDIO_FORMAT;
	pAviEncAudPara->channel_no			= 1;		//mono
	pAviEncAudPara->audio_sample_rate	= arg.AudSampleRate;

	pAviEncVidPara->sensor_width	= arg.SensorWidth;
	pAviEncVidPara->sensor_height	= arg.SensorHeight;

	pAviEncVidPara->clip_width		= arg.ClipWidth;
	pAviEncVidPara->clip_height		= arg.ClipHeight;

	pAviEncVidPara->zoom_width		= arg.ZoomWidth;
	pAviEncVidPara->zoom_height		= arg.ZoomHeight;
	pAviEncVidPara->zoom_w_start	= arg.ZoomWStart;
	pAviEncVidPara->zoom_h_start	= arg.ZoomHStart;
	
	pAviEncVidPara->zoom_width_r	= arg.ZoomWidth_r;
	pAviEncVidPara->zoom_height_r	= arg.ZoomHeight_r;
	pAviEncVidPara->zoom_w_start_r	= arg.ZoomWStart_r;
	pAviEncVidPara->zoom_h_start_r	= arg.ZoomHStart_r;	
	
	pAviEncVidPara->display_width	= arg.DisplayWidth;
	pAviEncVidPara->display_height	= arg.DisplayHeight;
	pAviEncVidPara->display_offset	= arg.DisplayOffset;

	pAviEncVidPara->pip_x			= arg.PipX;
	pAviEncVidPara->pip_y			= arg.PipY;
	pAviEncVidPara->pip_width		= arg.PipWidth;
	pAviEncVidPara->pip_height		= arg.PipHeight;

	pAviEncVidPara->video_format	= AVI_ENCODE_VIDEO_FORMAT;
	pAviEncVidPara->dwScale			= arg.bScaler;
	pAviEncVidPara->dwRate			= arg.VidFrameRate;
	pAviEncVidPara->encode_width	= arg.TargetWidth;
	pAviEncVidPara->encode_height	= arg.TargetHeight;
	pAviEncVidPara->enter_ap_mode	= arg.bEnterApMode;

	pAviEncVidPara->sensor_width_r	= arg.SensorWidth_r;
	pAviEncVidPara->sensor_height_r	= arg.SensorHeight_r;
	pAviEncVidPara->encode_width_r	= arg.TargetWidth_r;
	pAviEncVidPara->encode_height_r	= arg.TargetHeight_r;
	pAviEncVidPara->dwRate_r		= arg.VidFrameRate_r;

	nRet = vid_enc_preview_start();
	if(nRet < 0)
	{
		return CODEC_START_STATUS_ERROR_MAX;
	}

	return START_OK;
}

CODEC_START_STATUS video_encode_sensor_off(void)
{
	INT32S	nRet;

	nRet = vid_enc_preview_stop();
	if(nRet < 0)
	{
		return CODEC_START_STATUS_ERROR_MAX;
	}

	return START_OK;
}

/****************************************************************************/

/*
	video_encode_preview_on
 */
CODEC_START_STATUS video_encode_preview_on(INT32U mode)
{
	if(vid_enc_preview_buf_to_display(mode) < 0)
	{
		return CODEC_START_STATUS_ERROR_MAX;
	}

	return START_OK;
}

/****************************************************************************/

/*
	video_encode_preview_off
 */
CODEC_START_STATUS video_encode_preview_off(void)
{
	if(vid_enc_preview_buf_to_dummy() < 0)
	{
		return CODEC_START_STATUS_ERROR_MAX;
	}

	return START_OK;
}

CODEC_START_STATUS video_encode_record_start(MEDIA_SOURCE src, INT16S txt_handle)
{
	INT32S	nRet;

	DBG_PRINT("=>video_encode_record_start!!!\r\n");

	if(src.type == SOURCE_TYPE_FS)
		pAviEncPara->source_type = SOURCE_TYPE_FS;
	else
		return RESOURCE_WRITE_ERROR;

	if(src.type_ID.FileHandle < 0)
		return RESOURCE_NO_FOUND_ERROR;

#if C_REAR_ONLY == CUSTOM_ON
	nRet = avi_encode_set_file_handle_and_caculate_free_size(pAviEncPacker1, src.type_ID.FileHandle, -1);
#else
	nRet = avi_encode_set_file_handle_and_caculate_free_size(pAviEncPacker0, src.type_ID.FileHandle, txt_handle);
	if(nRet < 0)
		return RESOURCE_WRITE_ERROR;

	nRet = avi_encode_set_file_handle_and_caculate_free_size(pAviEncPacker1, src.type_ID.FileHandle_b, -1);
#endif

	//if(nRet < 0) return RESOURCE_WRITE_ERROR;
	pAviEncPacker0->file_handle_tmp = -1;	//open("C:\\DCIM\\DCIMA\\mova.tmp", O_WRONLY|O_CREAT|O_TRUNC);
	pAviEncPacker1->file_handle_tmp = -1;	//open("C:\\DCIM\\DCIMB\\movb.tmp", O_WRONLY|O_CREAT|O_TRUNC);

	//start avi packer

#if C_REAR_ONLY == CUSTOM_ON
	nRet = avi_enc_packer_start(pAviEncPacker1);
	if(nRet < 0)
	{
		return CODEC_START_STATUS_ERROR_MAX;
	}
#else
	nRet = avi_enc_packer_start(pAviEncPacker0);
	if(nRet < 0)
		return CODEC_START_STATUS_ERROR_MAX;

	if(src.type_ID.FileHandle_b >= 0)
	{
		nRet = avi_enc_packer_start(pAviEncPacker1);
		if(nRet < 0)
		{
			return CODEC_START_STATUS_ERROR_MAX;
		}
	}
#endif

	//start avi encode
	nRet = avi_enc_start();
	if(nRet < 0)
		return CODEC_START_STATUS_ERROR_MAX;

	return START_OK;
}

CODEC_START_STATUS video_encode_record_stop(void)
{
	INT32S	nRet, nTemp, i;

	DBG_PRINT("=>video_encode_record_stop!!!\r\n");

	if(pAviEncPacker0->file_handle >= 0)
	{
		for(i = 0; i < 10; i++)
		{
			if(AviPackerV3_CheckIfJpegExists((void *) pAviEncPacker0->avi_workmem))
			{
				break;
			}
			else
			{
				avi_encode_force_once_to_front();

				DBG_PRINT("wait front jpeg...\r\n");
				OSTimeDly(20);
			}
		}
	}

	if(pAviEncPacker1->file_handle >= 0)
	{
		for(i = 0; i < 10; i++)
		{
			if(AviPackerV3_CheckIfJpegExists((void *) pAviEncPacker1->avi_workmem))
			{
				break;
			}
			else
			{
				avi_encode_force_once_to_rear();

				DBG_PRINT("wait rear jpeg...\r\n");
				OSTimeDly(20);
			}
		}
	}

#if C_REAR_ONLY == CUSTOM_ON
	nTemp = avi_enc_packer_stop(pAviEncPacker1, 0);
#else
	nTemp = avi_enc_packer_stop(pAviEncPacker0, 0);
	nTemp |= avi_enc_packer_stop(pAviEncPacker1, 0);
#endif

	nRet = avi_enc_stop();
	avi_enc_buffer_free();
	if(nRet < 0 || nTemp < 0)
	{
		return CODEC_START_STATUS_ERROR_MAX;
	}

	/*
	close(pAviEncPacker0->file_handle_tmp); 
	close(pAviEncPacker1->file_handle_tmp);

	pAviEncPacker0->file_handle_tmp = -1;
	pAviEncPacker1->file_handle_tmp = -1;

	unlink("C:\\DCIM\\DCIMA\\mova.tmp");
	unlink("C:\\DCIM\\DCIMB\\movb.tmp"); */

	return START_OK;
}

CODEC_START_STATUS video_encode_record_restart(MEDIA_SOURCE src, INT16S next_txt_handle)
{
	INT32S	nRet;

	DBG_PRINT("=>video_encode_record_restart!!!\r\n");

	if(src.type == SOURCE_TYPE_FS)
		pAviEncPara->source_type = SOURCE_TYPE_FS;
	else
		return RESOURCE_WRITE_ERROR;

	if(src.type_ID.FileHandle < 0)
		return RESOURCE_NO_FOUND_ERROR;

#if C_REAR_ONLY == CUSTOM_ON
	nRet = avi_encode_set_file_handle_and_caculate_free_size(pAviEncPacker1, src.type_ID.FileHandle, -1);
#else
	nRet = avi_encode_set_file_handle_and_caculate_free_size(pAviEncPacker0, src.type_ID.FileHandle, next_txt_handle);
	if(nRet < 0)
		return RESOURCE_WRITE_ERROR;

	nRet = avi_encode_set_file_handle_and_caculate_free_size(pAviEncPacker1, src.type_ID.FileHandle_b, -1);
#endif

	//if(nRet < 0) return RESOURCE_WRITE_ERROR;
	//nRet = avi_enc_packer_switch_file(pAviEncPacker0, src.type_ID.FileHandle, next_txt_handle);
#if C_REAR_ONLY == CUSTOM_ON
	nRet = avi_enc_packer_start(pAviEncPacker1);
	if(nRet < 0)
	{
		return CODEC_START_STATUS_ERROR_MAX;
	}
#else
	nRet = avi_enc_packer_start(pAviEncPacker0);
	if(nRet < 0)
	{
		return CODEC_START_STATUS_ERROR_MAX;
	}

	//if((pAviEncPacker1->file_handle >= 0) && (src.type_ID.FileHandle_b >= 0)) {
	if(pAviEncPacker1->file_handle >= 0)
	{
		//nRet = avi_enc_packer_switch_file(pAviEncPacker1, src.type_ID.FileHandle_b, -1);
		nRet = avi_enc_packer_start(pAviEncPacker1);
		if(nRet < 0)
		{
			return CODEC_START_STATUS_ERROR_MAX;
		}
	}
#endif

	return START_OK;
}

CODEC_START_STATUS video_encode_capture_picture(MEDIA_SOURCE src)
{
	INT32S	nRet;

	DBG_PRINT("=>video_encode_capture_picture!!!\r\n");

	if(src.type_ID.FileHandle < 0)
	{
		return CODEC_START_STATUS_ERROR_MAX;
	}

#if C_REAR_ONLY == CUSTOM_ON
	pAviEncPacker0->file_handle = -1;
	pAviEncPacker1->file_handle = src.type_ID.FileHandle;
#else
	pAviEncPacker0->file_handle = src.type_ID.FileHandle;
	pAviEncPacker1->file_handle = src.type_ID.FileHandle_b;
#endif
	nRet = avi_enc_save_jpeg();
	return nRet;
}

#if C_SENSOR_SAVE_RAW_DATA
static INT32S cdsp_raw_data_save(void)
{
	INT32U			cdsp_raw_data_address;
	INT32U			cdsp_raw_data_size;
	INT16S			cdsp_raw_data_file_handle;
	INT8U			save_done = 0;

	CdspRawPara_t	CaptureArg;
	CdspRawPara_t	*pCaptureArg = &CaptureArg;

	// Change sensor to dummy address
	//video_preview_stop(0);
	cdsp_raw_data_file_handle = pAviEncPacker0->file_handle;

	pCaptureArg->InWidth = drv_l2_user_sensor_width_get();
	pCaptureArg->InHeight = drv_l2_user_sensor_height_get();;
	pCaptureArg->raw_bit = 10;
	pCaptureArg->capture_flag = 0;
	pCaptureArg->save_flag = 0;
	pCaptureArg->ImageSize = cdsp_raw_data_size = ((pCaptureArg->InWidth * (pCaptureArg->InHeight + 16)) * pCaptureArg->raw_bit / 8);
	pCaptureArg->Rawbuff = cdsp_raw_data_address = (INT32U) gp_malloc_align(cdsp_raw_data_size, 32);

	DBG_PRINT("\r\n=>Raw star addrs: 0x%x, Raw end addrs: 0x%x", cdsp_raw_data_address,(cdsp_raw_data_address+cdsp_raw_data_size));
	DBG_PRINT("\r\n=>Raw_Size:0x%x\r\n", pCaptureArg->ImageSize);
	gp_memset((INT8S *) cdsp_raw_data_address, 0, cdsp_raw_data_size);

	drv_l2_capture_raw_set_cfg(pCaptureArg);

	//save_raw10(cdsp_raw_data_address, MODE_LUTGAMMA);
	do
	{
		save_done = drv_l2_capture_raw_save_get();
		OSTimeDly(1);
	} while(!save_done);
	drv_l2_capture_raw_save_set(0);

	cache_invalid_range((cdsp_raw_data_address | 0x80000000), cdsp_raw_data_size);
	write(cdsp_raw_data_file_handle, (cdsp_raw_data_address | 0x80000000), cdsp_raw_data_size);
	OSTimeDly(1);
	close(cdsp_raw_data_file_handle);

	if(cdsp_raw_data_address)
	{
		gp_free((void *) cdsp_raw_data_address);
		pCaptureArg->Rawbuff = cdsp_raw_data_address = 0;
	}

	//cdsp_yuyv_restart(DUMMY_BUFFER_ADDRS);
	return STATUS_OK;
}
#endif

void video_encode_capture_raw_data(void)
{
#if C_SENSOR_SAVE_RAW_DATA
	INT8U	err;

	cdsp_raw_data_save();
	avi_encoder_state_clear(AVI_ENCODER_STATE_SENSOR);

	DBG_PRINT("=>video_encode_capture_raw_data DONE\r\n");
	err = 0;
	msgQSend(ApQ, MSG_STORAGE_SERVICE_PIC_DONE, &err, sizeof(INT8S), MSG_PRI_NORMAL);
#endif
}


